package com.ym.wcp.framework.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;


public class RedisUtil {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 清理所有redisConstantPrefix开头的缓存数据
     */
    @Async
    public void cleanByPrefix(String redisConstantPrefix) {
        try {
            Set<String> keys = getKeys(redisConstantPrefix + "*");
            if (!CollectionUtils.isEmpty(keys)) {
                dels(keys);
            }
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }

    public void put(String key, Object value) {
        try {
            if (value instanceof String) {
                stringRedisTemplate.opsForValue().set(key, (String) value);
            } else {
                redisTemplate.opsForValue().set(key, value);
            }
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }

    public void put(String key, Object value, long timeout, TimeUnit unit) {
        try {
            if (value instanceof String) {
                stringRedisTemplate.opsForValue().set(key, (String) value, timeout, unit);
            } else {
                redisTemplate.opsForValue().set(key, value, timeout, unit);
            }
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }


    public Object get(String key) {
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
        return null;
    }

    public Set<String> getKeys(String pattern) {
        try {
            return redisTemplate.keys(pattern);
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
        return null;
    }

    public void del(String key) {
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }

    public void dels(Collection<String> keys) {
        try {
            redisTemplate.delete(keys);
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }

    public void send(String channel, Object msg) {
        try {
            redisTemplate.convertAndSend(channel, msg);
        } catch (Exception e) {
            ExceptionInfoUtil.printStackTrace(e);
        } finally {
            closeTransactionSupport();
        }
    }

    public Long increment(String key, Integer self) {
        Long increment = getStringRedisTemplate().opsForValue().increment(key, self);
        if (increment == Long.MAX_VALUE) {
            del(key);
            increment = getStringRedisTemplate().opsForValue().increment(key, self);
        }
        return increment;
    }

    public StringRedisTemplate getStringRedisTemplate() {
        return stringRedisTemplate;
    }

    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    private void closeTransactionSupport() {
        RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
    }
}
